package query_in

import (
	"fmt"
	"rewords-server-2024/internal/dao/cmgox"
	"strconv"
	"strings"

	"go.mongodb.org/mongo-driver/bson"
)

// BuildMongoQuery 将通用查询条件转换为MongoDB查询条件
func BuildMongoQuery(conditions []Condition, orderFields []OrderField, fields []string) (query bson.M, sort bson.D, projection bson.M) {
	builder := cmgox.NewConditionBuilder()

	// 分别创建 AND 和 OR 条件的构建器
	andBuilder := cmgox.NewConditionBuilder()
	orBuilder := cmgox.NewConditionBuilder()

	// 处理查询条件
	for _, condition := range conditions {
		if condition.Disable {
			continue
		}

		// 处理字段值类型转换
		processedVals := processFieldValues(condition.Vals, condition.FieldType)
		if len(processedVals) == 0 {
			continue
		}

		// 根据条件类型构建查询
		currentBuilder := andBuilder
		if condition.Op == OpOr {
			currentBuilder = orBuilder
		}

		switch condition.ConditionType {
		case ConditionTypeEq:
			currentBuilder.AddCondition(condition.Field, "$eq", processedVals[0])
		case ConditionTypeNotEq:
			currentBuilder.AddCondition(condition.Field, "$ne", processedVals[0])
		case ConditionTypeLike:
			if strVal, ok := processedVals[0].(string); ok {
				regexPattern := convertLikeToRegex(strVal)
				currentBuilder.AddCondition(condition.Field, "$regex", regexPattern)
			}
		case ConditionTypeNotLike:
			if strVal, ok := processedVals[0].(string); ok {
				currentBuilder.AddCondition(condition.Field, "$not", bson.M{"$regex": strVal})
			}
		case ConditionTypeIn:
			currentBuilder.AddCondition(condition.Field, "$in", processedVals)
		case ConditionTypeNotIn:
			currentBuilder.AddCondition(condition.Field, "$nin", processedVals)
		case ConditionTypeGt:
			currentBuilder.AddCondition(condition.Field, "$gt", processedVals[0])
		case ConditionTypeLt:
			currentBuilder.AddCondition(condition.Field, "$lt", processedVals[0])
		case ConditionTypeGte:
			currentBuilder.AddCondition(condition.Field, "$gte", processedVals[0])
		case ConditionTypeLte:
			currentBuilder.AddCondition(condition.Field, "$lte", processedVals[0])
		case ConditionTypeBetween:
			if len(processedVals) == 2 {
				// 使用 bson.M 直接构建完整的范围条件
				rangeCondition := bson.M{
					"$gte": processedVals[0],
					"$lte": processedVals[1],
				}
				if condition.Op == OpOr {
					orBuilder.AddDynamicCondition(condition.Field, rangeCondition)
				} else {
					andBuilder.AddDynamicCondition(condition.Field, rangeCondition)
				}
			}
		}
	}

	// 合并 AND 和 OR 条件
	andConditions := andBuilder.Build()
	orConditions := orBuilder.Build()

	if len(andConditions) > 0 && len(orConditions) > 0 {
		builder.AddAndCondition([]bson.M{andConditions})
		builder.AddOrCondition([]bson.M{orConditions})
	} else if len(andConditions) > 0 {
		for k, v := range andConditions {
			builder.AddDynamicCondition(k, v.(bson.M))
		}
	} else if len(orConditions) > 0 {
		builder.AddOrCondition([]bson.M{orConditions})
	}

	// 处理排序条件
	if len(orderFields) > 0 {
		var sortFields bson.D
		for _, order := range orderFields {
			if order.Field == "" {
				continue
			}
			sortValue := 1 // 默认升序
			if order.OrderType == OrderTypeDesc {
				sortValue = -1
			}
			sortFields = append(sortFields, bson.E{Key: order.Field, Value: sortValue})
		}
		sort = sortFields
	}

	// 处理字段投影
	if len(fields) > 0 {
		projection = bson.M{}
		for _, field := range fields {
			if field != "" {
				projection[field] = 1
			}
		}
	}

	return builder.Build(), sort, projection
}

// BuildMongoQueryWithPage 构建带分页的MongoDB查询条件
func BuildMongoQueryWithPage(conditions []Condition, orderFields []OrderField, page *Page, fields []string) (query bson.M, skip int64, limit int64, sort bson.D, projection bson.M) {
	query, sort, projection = BuildMongoQuery(conditions, orderFields, fields)

	if page != nil {
		skip = page.Offset
		limit = page.Limit
	}

	return query, skip, limit, sort, projection
}

// convertLikeToRegex 将 SQL LIKE 模式转换为 MongoDB 正则表达式
func convertLikeToRegex(pattern string) string {
	// 转义特殊字符
	escapeChars := []string{".", "^", "$", "{", "}", "[", "]", "(", ")", "+", "?", "\\", "|"}
	for _, char := range escapeChars {
		pattern = strings.ReplaceAll(pattern, char, "\\"+char)
	}

	// 替换 SQL LIKE 通配符为正则表达式
	pattern = strings.ReplaceAll(pattern, "%", ".*")
	pattern = strings.ReplaceAll(pattern, "_", ".")

	// 确保模式匹配整个字符串
	pattern = "^" + pattern + "$"

	return pattern
}

// processFieldValues 处理字段值的类型转换
func processFieldValues(vals []any, fieldType string) []any {
	if len(vals) == 0 {
		return vals
	}

	processedVals := make([]any, len(vals))
	for i, val := range vals {
		switch fieldType {
		case FieldTypeInt:
			// 尝试将值转换为整数
			if strVal, ok := val.(string); ok {
				if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
					processedVals[i] = intVal
					continue
				}
			}
			processedVals[i] = val
		case FieldTypeString:
			// 确保值是字符串类型
			if str, ok := val.(string); ok {
				processedVals[i] = str
			} else {
				processedVals[i] = fmt.Sprintf("%v", val)
			}
		default:
			processedVals[i] = val
		}
	}
	return processedVals
}
